﻿@page "/datagrid"

@using FluentUI.Demo.Shared.Pages.DataGrid.Examples;
@using Microsoft.FluentUI.AspNetCore.Components;

<PageTitle>@App.PageTitle("DataGrid")</PageTitle>

<h1>Data grid</h1>
<p>
    The <code>&lt;FluentDataGrid&gt;</code> component is used to display tabular data. The <code>&lt;FluentDataGridRow&gt;</code>
    and <code>&lt;FluentDataGridCell&gt;</code> components are typically created programmatically by the parent grid but some
    authors may find it useful to create them manually.
</p>

<p>
    <div class="demopanel" style="margin: 1rem 0; padding: 1.5rem;">
        <h3>Important</h3>
        As of version 4.11.0, the DataGrid uses standard HTML table elements for rendering the grid (previously web components were used for this). When upgrading to this version, please be aware of the following:
        <ul>
            <li>A lot of changes have been made to the structure of the rendered content and the class names used. If you have been overriding grid classes in your own code, these probably no longer work.</li>
            <li>When you have rows in a table with content that needs to span multiple lines, you now need to use and set the new MultiLine (bool) parameter of the FluentDataGrid. Previously this could be done by setting a RowClass on a column but that does not work anymore</li>
            <li>
                The parameter <code>ResizeLabel</code> has been removed in favor of 3 new parameters. This makes changing strings in the DataGrid UI easier. See <FluentAnchor Href="#changeuistrings" Appearance="Appearance.Hypertext">Change strings used in the UI</FluentAnchor> for more information.
            </li>
            <li>It is currently not possible to use the <code>OnRowFocus</code> and <code>OnCellFocus</code> event callbacks. You can use the <code>OnRowClick</code>, <code>OnRowDoubleClick</code> and <code>OnCellClick</code> alternatives.

                As of v4.11.1 the <code>OnCellFocus</code> event callback will be operational again. For <code>OnRowFocus</code>, we are waiting for the necessary support being added by the different browsers. See https://chromestatus.com/feature/6237396851228672 for more information.
            </li>
        </ul>
    </div>
</p>

<p>
    Do not use the <code>RowStyle</code> parameter to dynamically update a row style after rendering (for example to highlight a row which was clicked on)
    as this will interfere with the DataGrid scripts that use this attribute as well. Use the <code>RowClass</code> instead.
</p>

<h2 id="a11y">Accessibility</h2>
<p>
    You can use the <kbd>Arrow</kbd> keys to navigate through a DataGrid. When a header cell is focused and the column is sortable, you can use the <kbd>Tab</kbd> key to select the sort button.
    Pressing the <kbd>Enter</kbd> key will toggle the sorting direction. Pressing <kbd>Ctrl+Enter</kbd> removes the column sorting and restores the default/start situation with regards to sorting.
    <em>You cannot remove the default grid sorting with this key combination.</em>
</p>
<p>
    When a header cell is focused and the column allows setting options, you can use the <kbd>Tab</kbd> key to select the options button.
    Pressing the <kbd>Enter</kbd> key then will toggle the options popover. Pressing <kbd>Esc</kbd> closes the popover
    .
</p>
<p>
    When a grid allows resizing of the columns, you can use the <kbd>+</kbd> and <kbd>-</kbd> keys to resize the column the focused header belongs to. Incrementing/decrementing
    width is done in steps of 10 pixels at a time. You can reset to the original initial column widths by pressing <kbd>Shift</kbd> + <kbd>r</kbd>.
</p>

<p>
    When a row cell is focused and the grid contains a <code>SelectColumn</code> column, you can use the <kbd>Enter</kbd> key to select or unselect the current row.
</p>

<h2 id="sorting">Sorting</h2>
<p>
    The DataGrid supports sorting by clicking on the column headers. The default sort direction is ascending. Clicking on the same column header again will toggle the sort direction.
    A sort can be removed by right clicking (or by pressing Shift+R) on the header column (with exception of the default sort).
</p>

<h2 id="styling">Row size</h2>
<p>
    As of v4.11.0, the Datagrid offers a <code>RowSize</code> parameter which allows you to use different preset row heights. The value uses the <code>DataGridRowSize</code> enumeration for its type.
    When using <code>Virtualize</code>, the <code>ItemSize</code> value is used is still used to indicate the row height.
</p>

<h2 id="styling">Resizing columns</h2>
<p>
    The DataGrid supports resizing columns by both dragging and through column option popups in exact or discrete mode. As of v4.12.0,
    the default behavior is to initiate a resize action by dragging the column edge on every row. In earlier versions this could only be done
    on the header column edge. To go back to the previous behavior, the new (as of v4.12.1) <code>ResizeColumnOnAllRows</code> parameter can be set to false.

</p>
<p>The following parameters can be used to tweak the resize handle appearance:</p>
    <CodeSnippet Language="css">.fluent-data-grid {
        --fluent-data-grid-resize-handle-color: var(--accent-fill-rest);
        --fluent-data-grid-resize-handle-width: 1px;
        --fluent-data-grid-header-opacity: 0.5;
        </CodeSnippet>

<h2 id="displaymode">DisplayMode</h2>
<p>
    The DataGrid supports 2 different display modes through the <code>DisplayMode</code> parameter: <code>DataGridDisplayMode.Grid</code> (default) and
    <code>DataGridDisplayMode.Table</code>. When set to <code>Grid</code>, the <code>GridTableColumns</code> parameter cam be used set specify column
    widths in fractions. It basically provides an HTML table element with a <code>display: grid;</code> style. The <code>Table</code> mode uses standard
    HTML table elements and rendering. Column widths in that mode are best specified through the <code>Width</code> parameter of the columns.
</p>
<p>
    Specifically when using <code>Virtualize</code>, it is <strong>higly recommended</strong> to use the <code>Table</code> display mode as the <code>Grid</code> mode
    can exhibit some odd behaviour when scrolling.
</p>


<h2 id="changeuistrings">Change strings used in the UI</h2>
<p>
    The DataGrid has a number of strings that are used in the UI. These can be changed by setting the <code>ColumnOptionLabels</code>, <code>ColumnResizeLabels</code> and <code>ColumnSortLabels</code> parameters.
    Each of these parameters is a record that contains properties for the strings that that specific piece of UI is using. There is a default implementation for each record.
    See below for a simplified example on how you can change these strings.
</p>
<CodeSnippet Language="razor">private ColumnResizeLabels _resizeLabels = ColumnResizeLabels.Default;
:
:
 protected override async Task OnInitializedAsync()
 {
     _resizeLabels = ColumnResizeLabels.Default with
     {
         ExactLabel = &quot;...&quot;,
         ResizeMenu = &quot;...&quot;

     };
:
:
</CodeSnippet>
<p>You only need to override the values that you actually want to change.</p>


<h2 if="usewithef">Using the DataGrid component with EF Core</h2>
<p>
    If you want to use the <code>FluentDataGrid</code> with data provided through EF Core, you need to install an additional package so the
    grid knows how to resolve queries asynchronously for efficiency.
</p>

<h3>Installation</h3>
    Install the package by running the command:
<CodeSnippet>dotnet add package Microsoft.FluentUI.AspNetCore.Components.DataGrid.EntityFrameworkAdapter</CodeSnippet>

<h3>Usage</h3>
    In your <code>Program.cs</code> file you need to add the following after the <code>builder.Services.AddFluentUIComponents();</code> line:
<CodeSnippet Language="csharp">builder.Services.AddDataGridEntityFrameworkAdapter();</CodeSnippet>

<h2 if="usewithodata">Using the DataGrid component with OData</h2>
<p><i>Added in 4.11.0</i></p>
<p>
    If you want to use the <code>FluentDataGrid</code> with data provided through OData, you need to install an additional package so the
    grid knows how to resolve queries asynchronously for efficiency.
</p>

<h3>Installation</h3>
    Install the package by running the command:
<CodeSnippet>dotnet add package Microsoft.FluentUI.AspNetCore.Components.DataGrid.ODataAdapter</CodeSnippet>

<h3>Usage</h3>
    In your <code>Program.cs</code> file you need to add the following after the <code>builder.Services.AddFluentUIComponents();</code> line:
<CodeSnippet Language="csharp">builder.Services.AddDataGridODataAdapter();</CodeSnippet>


<h2 id="example">Examples</h2>
<p>
    See the following pages for examples and additional documentation on the situations that ech example shows.
</p>
<FluentStack Orientation="Orientation.Vertical" Style="margin-bottom: 1rem;" >
    <h3>Basics</h3>
    <FluentAnchor Href="/datagrid-get-started" Appearance="Appearance.Hypertext">Getting started</FluentAnchor>
    <FluentAnchor Href="/datagrid-typical" Appearance="Appearance.Hypertext">Typical grid usage</FluentAnchor>
    <h3>Layout</h3>
    <FluentAnchor Href="/datagrid-loading-and-empty-content" Appearance="Appearance.Hypertext">...Content parameters</FluentAnchor>
    <FluentAnchor Href="/datagrid-auto-fit" Appearance="Appearance.Hypertext">Auto fit</FluentAnchor>
    <FluentAnchor Href="/datagrid-auto-items-per-page" Appearance="Appearance.Hypertext">Auto items per page</FluentAnchor>
    <FluentAnchor Href="/datagrid-custom-paging" Appearance="Appearance.Hypertext">Custom paging</FluentAnchor>
    <FluentAnchor Href="/datagrid-multi-line" Appearance="Appearance.Hypertext">Multi line text in cells</FluentAnchor>
    <FluentAnchor Href="/datagrid-scrollbars" Appearance="Appearance.Hypertext">Table with scrollbars</FluentAnchor>
    <h3>Sorting</h3>
    <FluentAnchor Href="/datagrid-custom-comparer-sort" Appearance="Appearance.Hypertext">Custom comparer</FluentAnchor>
    <FluentAnchor Href="/datagrid-custom-gridsort" Appearance="Appearance.Hypertext">Custom sorting</FluentAnchor>
    <h3>Columns</h3>
    <FluentAnchor Href="/datagrid-multi-select" Appearance="Appearance.Hypertext">Single/Multi select</FluentAnchor>
    <FluentAnchor Href="/datagrid-dynamic-columns" Appearance="Appearance.Hypertext">Dynamic columns</FluentAnchor>
    <FluentAnchor Href="/datagrid-header-generation" Appearance="Appearance.Hypertext">Header generation</FluentAnchor>
    <FluentAnchor Href="/datagrid-template-columns" Appearance="Appearance.Hypertext">Template columns</FluentAnchor>
    <FluentAnchor Href="/datagrid-template-columns-2" Appearance="Appearance.Hypertext">More template columns</FluentAnchor>
    <h3>Advanced</h3>
    <FluentAnchor Href="/datagrid-virtualize" Appearance="Appearance.Hypertext">Virtualized grid</FluentAnchor>
    <FluentAnchor Href="/datagrid-remote-data" Appearance="Appearance.Hypertext">Remote data</FluentAnchor>
    <FluentAnchor Href="/datagrid-manual" Appearance="Appearance.Hypertext">Manual grid</FluentAnchor>
    <FluentAnchor Href="/datagrid-menu-header" Appearance="Appearance.Hypertext">Menu header</FluentAnchor>
</FluentStack>

<h2 id="documentation">Documentation</h2>

<ApiDocumentation Component="typeof(FluentDataGrid<>)" GenericLabel="TGridItem" />

<ApiDocumentation Component="typeof(PropertyColumn<,>)" GenericLabel="TGridItem, TProp" InstanceTypes="@(new[] { typeof(string), typeof(string)  })" />

<ApiDocumentation Component="typeof(TemplateColumn<>)" GenericLabel="TGridItem" />

<ApiDocumentation Component="typeof(SelectColumn<>)" GenericLabel="TGridItem" />

<h3>Column menu labels and icons</h3>
<p>
    For customizing/translating the labels and icons used in the column menus, the following <code>records</code> are available. They can be applied
    to a grid by setting the respective parameters to an instance of these records. If you do not want to use an icon for a menu item, supply a null
    value to the Icon property in a record:
    <CodeSnippet>
        ColumnResizeLabels resizeLabels = ColumnResizeLabels.Default with
        {
            DiscreteLabel = "Abcd efg",
            ResetAriaLabel = "hij klm",
            Icon = null
        };
    </CodeSnippet>
</p>
<ApiDocumentation Component="typeof(ColumnSortLabels)" />
<ApiDocumentation Component="typeof(ColumnOptionsLabels)" />
<ApiDocumentation Component="typeof(ColumnResizeLabels)" />


<div class="demopanel">
    <p>
        <strong>The <code>FluentDataGridRow</code> and <code>FluentDataGridCell</code> API's are usually not used directly </strong>
    </p>
</div>

<ApiDocumentation Component="typeof(FluentDataGridRow<>)" GenericLabel="TGridItem" />

<ApiDocumentation Component="typeof(FluentDataGridCell<>)" GenericLabel="TGridItem" />

<ApiDocumentation Component="typeof(FluentPaginator)" />

<ApiDocumentation Component="typeof(PaginationState)" />

<h3>Refreshing data programmatically</h3>
<p>
    Sometimes you might know that the data source's contents will have changed. For example, the user may have saved some changes that will affect the data, or they might have changed the current query parameters. In any such case, you can call the grid's <code>RefreshDataAsync</code> method:
</p>

<CodeSnippet>
    &lt;FluentDataGrid ... @@ref="myGrid">
    ...
    &lt;/FluentDataGrid>

    @@code {
    FluentDataGrid&lt;MyDataType> myGrid;

    async Task HandleSomeEvent()
    {
    ...

    // We can force the grid to reload the current data
    await myGrid.RefreshDataAsync();
    }
    }
</CodeSnippet>
